#ifndef ATTRIBUTEINFO_H
#define ATTRIBUTEINFO_H
#include "SimpleIo.h"
#include "jtypes.h"
#include <vector>
#include "Assembler.h"

class ConstantPool;
class AttributeInfoLineNumberTable;

// known kind of attribute info
enum {
  aie_unknown,
  aie_code,
  aie_line_table
};

class AttributeInfo
{
  public:
    virtual void dump(ConstantPool *)=0;
    virtual void save(FILE *f,ConstantPool*)=0;
    virtual u4 getSavedLength()=0;

    u1 tag;
    u2 attribute_name_index;
};

class AttributeInfoCode : public AttributeInfo
{
  public:

    AttributeInfoCode(ConstantPool *, u2 attribute_name, FILE *f);
    AttributeInfoCode(ConstantPool *);

    virtual void dump(ConstantPool *) { };
    virtual void save(FILE*,ConstantPool*);
    virtual u4 getSavedLength();

    inline void disassemble(ConstantPool * cp) { assembler->disassemble(cp); };

    inline void assemble(u1 opcode, u4 operand) { assembler->assemble(opcode,operand); }
    inline void assemble(u1 opcode) { assembler->assemble(opcode); }
    inline u4 getAP()               { return assembler->getAP(); }

    inline void assembleAt(u4 offset,u1 opcode, u4 operand) { assembler->assembleAt(offset,opcode,operand); }
    inline void relocAt(u4 offset,u4 operand) { assembler->relocAt(offset,operand); }

    void resetCode();

  private:

    struct exception {
      u2   start_pc;
      u2   end_pc;
      u2   handler_pc;
      u2   catch_type;
    };

    u4 attribute_length;
    u2 max_stack;
    u2 max_locals;

    Assembler * assembler;
    AttributeInfoLineNumberTable * lineTable;

    u2  n_exceptions;
    exception * exceptions;
    
    std::vector<AttributeInfo*>  attributes;
};

class AttributeInfoLineNumberTable : public AttributeInfo
{
  public:
    AttributeInfoLineNumberTable(ConstantPool *, u2 attribute_name, FILE *f);

    virtual void dump(ConstantPool *) { };

    virtual void save(FILE*,ConstantPool*);

    virtual u4   getSavedLength();

    u2   addr2Line(u2 addr);

    void resetTable();


  private:
    struct ltable {
      u2 start_pc;
      u2 line_number;
    };

    u2 attribute_length;
    std::vector<ltable> table;
};


class AttributeInfoFactory 
{
  public:
    static AttributeInfo * fromFile(ConstantPool * cp,FILE *f);
};
#endif
